/*
 * Copyright (C) 2010 TopCoder Inc., All Rights Reserved.
 */
package com.hercules.xre.protocol.testing.netty.websocket;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.ChannelHandler.Sharable;
import org.jboss.netty.handler.codec.http.websocket.DefaultWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocket.WebSocketFrame;

import com.hercules.xre.protocol.testing.netty.BaseProtocolTestingConnectionManager;

/**
 * <p>
 * A web socket frame which converts WebSocketFrame to String (Upstream) and String to WebSocketFrame (Downstream).
 * </p>
 * <p>
 * Thread Safety :This class is not thread safe.
 * </p>
 *
 * @author TCSASSEMBLER
 * @version 1.0
 */
@Sharable
public class WebSocketFrameBufferAdapter extends SimpleChannelHandler {
    /**
     * <p>
     * Connection manager that is used to fetch sessionGUID for current channel.
     * Set in the constructor, never changes after that.
     * </p>
     */
    private final BaseProtocolTestingConnectionManager connectionManager;

    /**
     * <p>
     * Creates new instance.
     * </p>
     *
     * @param connectionManager
     *            connection manager, can't be null
     */
    public WebSocketFrameBufferAdapter(BaseProtocolTestingConnectionManager connectionManager) {
        this.connectionManager = connectionManager;
    }

    /**
     * Method called when web socket frame has been received.
     *
     * @param ctx
     *            channel handler context, can't be null
     * @param e
     *            message event, can't be null
     * @throws Exception
     *             if any error occurs
     */
    @SuppressWarnings("deprecation")
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        Object messageObject = e.getMessage();
        if (!(messageObject instanceof WebSocketFrame)) {
            Channels.fireMessageReceived(ctx, messageObject, e.getRemoteAddress());
        } else {
            //converts WebSocketFrame to String
            WebSocketFrame frame = (WebSocketFrame) messageObject;
            Channels.fireMessageReceived(ctx, frame.getBinaryData().toString("UTF-8"), e.getRemoteAddress());
        }
    }

    /**
     * Method called when write is requested..
     *
     * @param ctx
     *            channel handler context, can't be null
     * @param e
     *            message event, can't be null
     * @throws Exception
     *             if any error occurs
     */
    @Override
    public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        Object messageObject = e.getMessage();

        if (!(messageObject instanceof String)) {
            Channels.write(ctx, e.getFuture(), messageObject, e.getRemoteAddress());
        } else {
            //converts String to WebSocketFrame
            messageObject = connectionManager.prepareCommandToSend((String) messageObject, ctx.getChannel());
            WebSocketFrame frame = new DefaultWebSocketFrame((String) messageObject);

            Channels.write(ctx, e.getFuture(), frame, e.getRemoteAddress());
        }
    }
}
